/*
 * 您可以使用ASP.NET Core MVC过滤器来执行一些Orchard特定的操作，例如将形状或资源注入到您的页面中。
 * 这里您将看到两个示例。
 *
 * 这个过滤器将是一个可以临时形状注入到区域的过滤器。一个常见的场景是向每个页面注入横幅，
 * 以通知用户重要的事情。
 *
 * 第二个过滤器（ResourceInjectionFilter）将是向页面注入资源（脚本或样式表）的示例。
 * 在示例中，如果URL包含"fadeIn"查询字符串参数，将注入样式表，这将在加载时使页面淡入。
 *
 * 第三个过滤器ResourceFromShapeInjectingFilter将结合两者，完全让您惊叹！
 *
 * 主要功能：
 * - 演示形状注入过滤器的使用
 * - 展示如何向页面区域注入临时形状
 * - 演示布局访问器的使用
 * - 展示形状工厂的使用
 */

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.Layout;
using System.Threading.Tasks;

namespace Lombiq.TrainingDemo.Filters;

/// <summary>
/// 形状注入过滤器 - 向页面区域注入临时形状
/// 
/// 主要用途：
/// - 向页面区域注入临时形状
 /* - 演示布局访问器的使用
 * - 展示形状工厂的使用
 * - 实现动态内容注入
 * 
 * 使用场景：
 * - 向每个页面注入横幅通知
 * - 动态添加页面内容
 * - 实现全局内容注入
 * - 展示形状注入的最佳实践
 * 
 * 设计原因：
 * - 提供动态内容注入机制
 * - 演示Orchard Core过滤器的使用
 * - 展示布局和形状系统的集成
 * - 实现可重用的内容注入功能
 * 
 * 设计模式：
 * - 过滤器模式：实现IAsyncResultFilter接口
 * - 依赖注入模式：通过构造函数注入服务
 * - 布局模式：使用ILayoutAccessor访问布局
 * - 形状模式：使用IShapeFactory创建形状
/// </summary>
// 不要忘记在Startup.cs文件中的过滤器集合中添加此过滤器。
 */
public sealed class ShapeInjectionFilter : IAsyncResultFilter
{
    // 要访问包含区域的布局，您需要使用ILayoutAccessor服务。
    private readonly ILayoutAccessor _layoutAccessor;

    // 要生成临时形状，可以使用IShapeFactory。这与您之前在AdHocShape.cshtml中看到的模板中的New属性相同。
    private readonly IShapeFactory _shapeFactory;

    /// <summary>
    /// 构造函数 - 注入所需的服务依赖
    /// </summary>
    /// <param name="layoutAccessor">布局访问器，用于访问页面布局</param>
    /// <param name="shapeFactory">形状工厂，用于创建临时形状</param>
    public ShapeInjectionFilter(ILayoutAccessor layoutAccessor, IShapeFactory shapeFactory)
    {
        _layoutAccessor = layoutAccessor;
        _shapeFactory = shapeFactory;
    }

    /// <summary>
    /// 结果执行方法 - 在结果执行时注入形状
    /// 
    /// 功能说明：
    /// - 检查结果类型是否为ViewResult或PageResult
    /// - 获取页面布局
    /// - 向Content区域注入临时形状
    /// - 继续执行后续过滤器
    /// 
    /// 执行流程：
    /// 1. 检查结果类型，确保有区域可以注入
    /// 2. 获取页面布局
    /// 3. 访问Content区域
    /// 4. 创建并注入临时形状
    /// 5. 继续执行后续过滤器
    /// </summary>
    /// <param name="context">结果执行上下文</param>
    /// <param name="next">下一个执行委托</param>
    /// <returns>完成的任务</returns>
    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        // 您可以在这里决定何时执行过滤器。如果这不是ViewResult或PageResult，形状注入就没有意义，
        // 因为不会有任何区域。
        if (context.Result is not (ViewResult or PageResult))
        {
            await next();

            return;
        }

        // 我们首先检索布局。
        var layout = await _layoutAccessor.GetLayoutAsync();

        // Layout对象将包含一个Zones字典，您可以使用它来访问区域。Content区域通常在所有主题中都可用，
        // 是每个页面中间的主要区域。
        var contentZone = layout.Zones["Content"];
        // 在这里，您可以将临时生成的形状添加到Content区域。这与我们之前讨论显示管理时看到的方式相同。
        // 您可以在Views/InjectedShape.cshtml下找到将渲染此形状的模板。
        await contentZone.AddAsync(await _shapeFactory.CreateAsync("InjectedShape"));

        await next();
    }
}

// 下一站：Filters/ResourceInjectionFilter.cs
